feat: Add execution statistics storage and dashboard graph#1896
feat: Add execution statistics storage and dashboard graph#1896
Conversation
- Add ExecutionStat data structure for daily execution counts - Implement GetExecutionStats and IncrementExecutionStat in storage - Update SetExecutionDone to track statistics on execution completion - Add GET /v1/stats API endpoint with configurable days parameter - Create ExecutionStatsChart React component with stacked area chart - Integrate statistics graph into UI dashboard - Add comprehensive tests for execution statistics functionality - Fix pre-existing import path issue in grpc_test.go
📝 WalkthroughWalkthroughAdds daily execution statistics: new storage API and store implementation, a GET /v1/stats HTTP endpoint, data models and tests, and a React dashboard chart that fetches and displays the last 30 days of execution success/failure counts. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as "Browser UI"
participant API as "HTTPTransport / API (GET /v1/stats)"
participant Store as "Store"
participant KV as "KV storage"
UI->>API: GET /v1/stats?days=30
API->>Store: GetExecutionStats(ctx, days)
Store->>KV: Read keys stats:YYYY-MM-DD...
KV-->>Store: JSON stat entries (or missing)
Store-->>API: ExecutionStats JSON
API-->>UI: 200 OK + stats JSON
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@dkron/api.go`:
- Around line 553-568: In statsHandler, validate the days query param (daysStr)
after parsing: if strconv.Atoi fails or the parsed days is <= 0 return a 400 Bad
Request with a clear error message; otherwise cap days to a reasonable maximum
(e.g., maxDays := 365) before calling h.agent.Store.GetExecutionStats so
extremely large values are reduced. Update the handler to use the
validated/capped days value and keep the existing error logging for the
GetExecutionStats call.
In `@dkron/execution_stats_test.go`:
- Around line 22-24: The test uses time.Now() to set the variable now (and again
later) which makes the test flaky; replace time.Now() with a fixed UTC time
value (e.g., a time.Date(...) constant) and use that fixed variable wherever now
is used in the file (including the occurrences around lines where now is set and
the later uses at ~128-129) so the test is deterministic across time zones/DST;
update the variable declaration (currently "now") and any assertions that depend
on it (in the test functions in dkron/execution_stats_test.go) to reference this
fixed UTC timestamp.
In `@dkron/store.go`:
- Around line 951-995: The GetExecutionStats method allows an unbounded days
parameter which can lead to large allocations and long loops; add an upper bound
(e.g., maxDays := 365) and clamp days = max(1, min(days, maxDays)) before
allocating stats and iterating. Update the allocation of stats.Stats to use the
clamped days value and iterate that many days using the existing loop logic in
Store.GetExecutionStats so memory and work are limited.
In `@ui/src/dashboard/ExecutionStatsChart.tsx`:
- Around line 33-36: The dateFormatter function currently formats dates in the
user’s local timezone which mismatches the backend’s UTC-day aggregation; update
the dateFormatter (const dateFormatter) to pass timeZone: 'UTC' in the options
to toLocaleDateString (e.g., { month: 'short', day: 'numeric', timeZone: 'UTC'
}) so the frontend labels align with backend UTC truncation.
| func (h *HTTPTransport) statsHandler(c *gin.Context) { | ||
| daysStr := c.DefaultQuery("days", "30") | ||
| days, err := strconv.Atoi(daysStr) | ||
| if err != nil { | ||
| days = 30 | ||
| } | ||
|
|
||
| stats, err := h.agent.Store.GetExecutionStats(c.Request.Context(), days) | ||
| if err != nil { | ||
| h.logger.WithError(err).Error("api: Unable to get execution stats") | ||
| c.AbortWithStatus(http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| renderJSON(c, http.StatusOK, stats) | ||
| } |
There was a problem hiding this comment.
Validate and cap the days query parameter.
Line 554 accepts any value; negative or very large inputs can lead to unexpected ranges or excessive work. Consider enforcing a positive range and a reasonable maximum (e.g., 365).
🔧 Suggested bounds handling
- daysStr := c.DefaultQuery("days", "30")
- days, err := strconv.Atoi(daysStr)
- if err != nil {
- days = 30
- }
+ const (
+ defaultStatsDays = 30
+ maxStatsDays = 365
+ )
+ daysStr := c.DefaultQuery("days", strconv.Itoa(defaultStatsDays))
+ days, err := strconv.Atoi(daysStr)
+ if err != nil || days <= 0 {
+ days = defaultStatsDays
+ }
+ if days > maxStatsDays {
+ days = maxStatsDays
+ }🤖 Prompt for AI Agents
In `@dkron/api.go` around lines 553 - 568, In statsHandler, validate the days
query param (daysStr) after parsing: if strconv.Atoi fails or the parsed days is
<= 0 return a 400 Bad Request with a clear error message; otherwise cap days to
a reasonable maximum (e.g., maxDays := 365) before calling
h.agent.Store.GetExecutionStats so extremely large values are reduced. Update
the handler to use the validated/capped days value and keep the existing error
logging for the GetExecutionStats call.
| ctx := context.Background() | ||
| now := time.Now() | ||
|
|
There was a problem hiding this comment.
Stabilize time-dependent tests.
Line 23 and Line 128 use time.Now(), which can be flaky around midnight/DST. Use a fixed UTC time for deterministic results.
🧪 Deterministic time setup
- now := time.Now()
+ now := time.Date(2025, 1, 2, 12, 0, 0, 0, time.UTC)
...
- now := time.Now()
+ now := time.Date(2025, 1, 2, 12, 0, 0, 0, time.UTC)Also applies to: 128-129
🤖 Prompt for AI Agents
In `@dkron/execution_stats_test.go` around lines 22 - 24, The test uses time.Now()
to set the variable now (and again later) which makes the test flaky; replace
time.Now() with a fixed UTC time value (e.g., a time.Date(...) constant) and use
that fixed variable wherever now is used in the file (including the occurrences
around lines where now is set and the later uses at ~128-129) so the test is
deterministic across time zones/DST; update the variable declaration (currently
"now") and any assertions that depend on it (in the test functions in
dkron/execution_stats_test.go) to reference this fixed UTC timestamp.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
|
@copilot add the new endpoint to the OpenAPI spec |
|
@vcastellm I've opened a new pull request, #1900, to work on those changes. Once the pull request is ready, I'll request review from you. |
* Initial plan * feat: Add /stats endpoint to OpenAPI specification Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com>
|
@copilot check these errors: |
|
@vcastellm I've opened a new pull request, #1901, to work on those changes. Once the pull request is ready, I'll request review from you. |
…#1901) * Initial plan * fix: Remove extraneous closing brace in store.go Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com>
Merged latest changes from main branch (commit 2b5f80b) into the E2E test PR branch. Conflict resolution strategy: - Accepted main branch version for all source files (Go code, UI, configs) - Preserved E2E test infrastructure (e2e/ directory and all test files) - Added e2e, e2e-quick, e2e-debug targets back to Makefile - Kept .github/workflows/e2e.yml workflow file New features from main now included: - Redesigned UI with modern professional styling (#1894) - Execution statistics storage and dashboard graph (#1896) - Plugin health monitoring in /health endpoint (#1884) - Retry logic with exponential backoff for AgentRun RPC (#1882) - Various dependency updates Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com>
* Initial plan * Merge main branch into E2E test suite PR Merged latest changes from main branch (commit 2b5f80b) into the E2E test PR branch. Conflict resolution strategy: - Accepted main branch version for all source files (Go code, UI, configs) - Preserved E2E test infrastructure (e2e/ directory and all test files) - Added e2e, e2e-quick, e2e-debug targets back to Makefile - Kept .github/workflows/e2e.yml workflow file New features from main now included: - Redesigned UI with modern professional styling (#1894) - Execution statistics storage and dashboard graph (#1896) - Plugin health monitoring in /health endpoint (#1884) - Retry logic with exponential backoff for AgentRun RPC (#1882) - Various dependency updates Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Fix unresolved merge conflict in ui/src/layout/index.css Replaced file with clean version from main branch to remove conflict markers. Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com>
* Add comprehensive E2E test suite for Dkron API - Create e2e test infrastructure using Bats (Bash Automated Testing System) - Add Docker Compose setup for isolated e2e testing environment - Add 71 tests covering: - Health, cluster, leader, and debug endpoints (19 tests) - Job CRUD operations including timezone, retries, concurrency (24 tests) - Job execution and scheduling (17 tests) - Pause/unpause functionality (11 tests) - Add helper functions for API requests, response parsing, and assertions - Add test runner script with options for filtering, verbose output, and debugging - Add Makefile targets: e2e, e2e-quick, e2e-debug Key findings documented in tests: - Disabled jobs cannot be manually triggered via /run endpoint - Pause only blocks new job creation, not scheduled execution - Timezone jobs require 6-field cron expressions (with seconds) * Add Algolia site verification meta tag * Apply suggestion from @coderabbitai[bot] Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Add GitHub Actions workflow for E2E tests (#1899) * Initial plan * Add GitHub Actions workflow for E2E tests Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Fix workflow: remove invalid tags-ignore and use apt for bats Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Add explicit permissions to e2e workflow Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Merge main branch into E2E test suite PR (#1902) * Initial plan * Merge main branch into PR branch - resolve conflicts Merged latest changes from main branch (commit 28f91f1) into the E2E test PR branch. Conflict resolution: - Accepted main branch version for all source files (Go code, UI, configs) - Preserved E2E test infrastructure (e2e/ directory and all test files) - Added e2e, e2e-quick, e2e-debug targets back to Makefile - Kept .github/workflows/e2e.yml workflow file New features from main now included: - Execution statistics storage and dashboard graph - Plugin health monitoring - Retry logic with exponential backoff for AgentRun RPC - Various dependency updates Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Update E2E test to use bare endpoint /v1/jobs/:job (#1897) * Initial plan * Update first test to use bare endpoint /v1/jobs/:job Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Fix flaky E2E test using deterministic polling instead of fixed sleep (#1898) * Initial plan * Replace sleep 3 with wait_for_execution for deterministic test behavior Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Update dkron/api_test.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Fix syntax error in TestHealthEndpoint causing compilation failure (#1906) * Initial plan * Fix syntax error in api_test.go - remove duplicate closing brace Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Fix retry loop skipping when AgentRunMaxRetries is negative (#1905) * Initial plan * Fix retry loop to ensure at least one attempt when maxRetries is negative Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Enhance E2E test to validate failed execution success field (#1904) * Initial plan * Enhance failed job execution test to assert success=false Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Remove beta dependency by downgrading protoreflect to v1.17.0 (#1903) * Initial plan * Downgrade protoreflect from v1.18.0 to v1.17.0 to remove beta v2 dependency Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Add comprehensive E2E test suite for Dkron API (#1907) * Initial plan * Merge main branch into E2E test suite PR Merged latest changes from main branch (commit 2b5f80b) into the E2E test PR branch. Conflict resolution strategy: - Accepted main branch version for all source files (Go code, UI, configs) - Preserved E2E test infrastructure (e2e/ directory and all test files) - Added e2e, e2e-quick, e2e-debug targets back to Makefile - Kept .github/workflows/e2e.yml workflow file New features from main now included: - Redesigned UI with modern professional styling (#1894) - Execution statistics storage and dashboard graph (#1896) - Plugin health monitoring in /health endpoint (#1884) - Retry logic with exponential backoff for AgentRun RPC (#1882) - Various dependency updates Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> * Fix unresolved merge conflict in ui/src/layout/index.css Replaced file with clean version from main branch to remove conflict markers. Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: vcastellm <47026+vcastellm@users.noreply.github.com>
Proposed changes
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request.
If it fixes a bug or resolves a feature request, be sure to link to that issue.
Types of changes
What types of changes does your code introduce?
Put an
xin the boxes that applySummary by CodeRabbit
New Features
Documentation
Tests
✏️ Tip: You can customize this high-level summary in your review settings.